package de.hsmannheim.poolraumapp;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTimeConstants;
import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import org.jsoup.helper.StringUtil;

import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;

import de.hsmannheim.poolraumapp.db.RoomSearcher;
import de.hsmannheim.poolraumapp.model.RoomQuery;
import de.hsmannheim.poolraumapp.model.RoomQuery.WhatOS;
import static de.hsmannheim.poolraumapp.model.RoomQuery.*;

import android.app.Application;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;

public class PoolraumApp extends Application implements Observer {
	private static final String TAG = PoolraumApp.class.getName();
	
	private RoomQuery roomQuery;
	
	private static final String QUERY_PREF_NAME = "queryPrefs";
	
	private static final String FORMAT_DATE = "YYYY-MM-dd";
	private static final String FORMAT_TIME = "HH:mm:ss";
	
	private Gson gson = new Gson();

	private Type osType = new TypeToken<List<WhatOS>>(){}.getType();	
	
	private RoomSearcher roomSearcher;
	
	@Override
	public void onCreate() {
		super.onCreate();
		startService(new Intent(this, FetcherService.class));
	}	

	@SuppressWarnings("unchecked")
	public synchronized RoomQuery getRoomQuery() {
		Log.d(TAG, "getRoomQuery called");
		if (roomQuery == null) {
			Log.d(TAG, "roomQuery not yet initialized");
			SharedPreferences prefs = getSharedPreferences(QUERY_PREF_NAME, MODE_PRIVATE);
			roomQuery = new RoomQuery();
			roomQuery.setDay(RoomQuery.WhenDay.valueOf(prefs.getString(DAY, RoomQuery.WhenDay.TODAY.name()))); 
			roomQuery.setWeekday(prefs.getInt(WEEKDAY, DateTimeConstants.MONDAY));
			roomQuery.setDate(new LocalDate(prefs.getString(DATE, new LocalDate().toString(FORMAT_DATE))));
			roomQuery.setTime(RoomQuery.WhenTime.valueOf(prefs.getString(TIME, RoomQuery.WhenTime.NOW.name())));
			String now = new LocalTime().toString(FORMAT_TIME);
			roomQuery.setTimePoint(new LocalTime(prefs.getString(TIME_POINT, now)));
			roomQuery.setFrom(new LocalTime(prefs.getString(FROM, now)));
			roomQuery.setTo(new LocalTime(prefs.getString(TO, now)));
			roomQuery.setWhere(RoomQuery.Where.valueOf(prefs.getString(WHERE, RoomQuery.Where.ANYWHERE.name())));
			roomQuery.setBuildings(Sets.newHashSet(Splitter.fixedLength(1).omitEmptyStrings().split(prefs.getString(BUILDINGS, ""))));
			roomQuery.setWhat(RoomQuery.What.valueOf(prefs.getString(WHAT, RoomQuery.What.ANY_OF.name())));
			roomQuery.setOS(new HashSet<WhatOS>((List<WhatOS>)gson.fromJson(prefs.getString(OS, "[ 'WINDOWS', 'LINUX', 'MAC' ]"), osType)));
			roomQuery.addObserver(this);
		}
		Log.d(TAG, "getRoomQuery finished");
		return roomQuery;
	}

	@Override
	public void update(Observable arg0, Object arg1) {
		Log.d(TAG, "updating query prefs");
		Editor prefEditor = getSharedPreferences(QUERY_PREF_NAME, MODE_PRIVATE).edit();
		prefEditor.putString(DAY, roomQuery.getDay().name());
		prefEditor.putInt(WEEKDAY, roomQuery.getWeekday());
		prefEditor.putString(DATE, roomQuery.getDate().toString(FORMAT_DATE));
		prefEditor.putString(TIME, roomQuery.getTime().name());
		prefEditor.putString(TIME_POINT, roomQuery.getTimePoint().toString(FORMAT_TIME));
		prefEditor.putString(FROM, roomQuery.getFrom().toString(FORMAT_TIME));
		prefEditor.putString(TO, roomQuery.getTo().toString(FORMAT_TIME));
		prefEditor.putString(WHERE, roomQuery.getWhere().name());
		prefEditor.putString(BUILDINGS, StringUtils.join(roomQuery.getBuildings(), ""));
		prefEditor.putString(WHAT, roomQuery.getWhat().name());
		prefEditor.putString(OS, gson.toJson(roomQuery.getOS()));
		Log.d(TAG, "query prefs updated");
		prefEditor.commit();
	}
	
	public RoomSearcher getRoomSearcher() {
		if (roomSearcher == null){
			roomSearcher = new RoomSearcher(this);
		}
		return roomSearcher;
	}
}
